﻿using KinonekoSoftware.CodariaDB.Documents.Shenanigans.Forum;
using KinonekoSoftware.Studio.Enums;
using KinonekoSoftware.Studio.Models.Shenanigans.Forums;
using PlainTextMSG = KinonekoSoftware.Studio.Models.Shenanigans.Forums.PlainTextMSG;
using Verbose = KinonekoSoftware.Studio.Messages.Verbose;

namespace KinonekoSoftware.Studio.Pages.Shenanigans
{
    public sealed partial class ForumEditorViewModel : TabViewModelCore
    {
        private readonly CharacterDataSource _characterDataSource;
        private readonly ForumEngine         _engine_forum;
        private readonly ImageSystem         _engine_image;

        private Discuss _discuss;


        public ForumEditorViewModel()
        {
            Platform.GetEngine<ForumEngine, ImageSystem>(out _,
                                                         out _engine_forum,
                                                         out _engine_image);
            //
            //
            _msgCreationFlag = ForumMSGCreationFlag.PlainText;
            _creationType = new EnumMaster<ForumMSGCreationFlag>
            {
                Value = ForumMSGCreationFlag.PlainText,
            };
            _attachmentMode = _creationType.SingleSelect(nameof(IsAttachmentCreationMode), ForumMSGCreationFlag.Attachment, RaiseUpdated);
            _plainTextMode  = _creationType.SingleSelect(nameof(IsPlainTextCreationMode), ForumMSGCreationFlag.PlainText, RaiseUpdated);
            _imageMode      = _creationType.SingleSelect(nameof(IsImageCreationMode), ForumMSGCreationFlag.Image, RaiseUpdated);

            _characterDataSource    = new CharacterDataSource();
            _ForumMessageIDMap      = new Dictionary<string, ForumMSG>();
            _ForumMessageCollection = new List<ForumMSG>();
            PagedMessages           = new ObservableCollection<ForumMSG>();

            SaveCommand = CreateCommand(Save);

            AddCharacterCommand       = CreateCommand(DoAddCharacterCommand);
            UpdateCharacterCommand    = CreateCommand(DoUpdateCharacterCommand);
            PreviousPageCommand       = CreateCommand(DoPreviousPageCommand);
            NextPageCommand           = CreateCommand(DoNextPageCommand);
            RemoveCharacterCommand    = CreateCommand<Character>(DoRemoveCharacterCommand);
            RemoveAllCharacterCommand = CreateCommand(DoRemoveAllCharacterCommand);

            AddImageToMessageCommand       = CreateCommand(DoAddImageToMessageCommand);
            EditMessageCommand             = CreateCommand<ForumMSG>(DoEditMessageCommand);
            ReplyMessageCommand            = CreateCommand<ForumMSG>(DoReplyMessageCommand);
            RemoveMessageCommand           = CreateCommand<ForumMSG>(DoRemoveMessageCommand);
            ShiftUpImageToMessageCommand   = CreateCommand<string>(DoShiftUpImageToMessageCommand);
            ShiftDownImageToMessageCommand = CreateCommand<string>(DoShiftDownImageToMessageCommand);
            RemoveImageToMessageCommand    = CreateCommand<string>(DoRemoveImageToMessageCommand);
            SendNewMessageCommand          = CreateCommand(DoSendNewMessageCommand);
            NewDiscussCommand              = CreateCommand<ForumMSG>(DoNewDiscussCommand);

            //
            // 确保全局数据已经加载。
            CharacterDataSource.Initialize();

            IsSingleton      = false;
            Removable        = true;
            EnableSafetyExit = true;
        }

        private void Initialize()
        {
            //
            //
            var members = _discuss.Members.Select(x => _characterDataSource.ScopedGet(x));

            //
            //
            _characterDataSource.ScopedClear();
            _characterDataSource.ScopedAdd(Owner);
            _characterDataSource.Initialize(members);

            //
            //
            var queue = new Queue<ReplyForumObject>();

            //
            // 第一遍仅添加非Reply的消息。
            for (var i = 0; i < _discuss.Threads.Count; i++)
            {
                var item = _discuss.Threads[i];
                var msg  = item is ReplyForumObject ? null : Build(item);

                //
                //
                _ForumMessageIDMap.Add(item.Id, msg);
            }

            for (var i = 0; i < _discuss.Threads.Count; i++)
            {
                var item = _discuss.Threads[i];

                if (item is not ReplyForumObject rfo)
                {
                    continue;
                }

                if (!_ForumMessageIDMap.TryGetValue(rfo.ReferenceID, out var reference))
                {
                    //
                    // 无效消息，移除。
                    _discuss.Threads.RemoveAt(i);
                    _ForumMessageIDMap.Remove(rfo.ReferenceID);
                }

                if (reference is null)
                {
                    //
                    //
                    queue.Enqueue(rfo);
                }
                else
                {
                    //
                    // 添加
                    _ForumMessageIDMap[item.Id] = Build(rfo);
                }
            }

            //
            //
            for (var loop = 0; loop < queue.Count; loop++)
            {
                for (var i = 0; i < _discuss.Threads.Count; i++)
                {
                    var item      = queue.Dequeue();
                    var reference = _ForumMessageIDMap.GetValueOrDefault(item.ReferenceID);

                    if (reference is null)
                    {
                        //
                        //
                        queue.Enqueue(item);
                    }
                    else
                    {
                        //
                        // 添加
                        _ForumMessageIDMap[item.Id] = Build(item);
                    }
                }
            }

            foreach (var msg in _discuss.Threads.Select(x => _ForumMessageIDMap.GetValueOrDefault(x.Id)))
            {
                //
                //
                _ForumMessageCollection.Add(msg);
            }

            //
            //
            Page();

            Title  = _discuss.Name;
            Poster = Owner;

            RaiseUpdated(nameof(MessageCount));
        }



        private async void Save()
        {
            //
            //
            _engine_forum.Update(_discuss);

            //
            //
            SetDirtyState(false);

            //
            //
            await Success(TitleSR.SuccessOperation, TextSR.Successful_Save);
        }

        protected override async void OnReceive(PageContext context)
        {
            _discuss = context.GetObject<Discuss>(ContextBase.Key_Value);

            if (_discuss is null)
            {
                await Danger("", "这个帖子本该拥有数据，但奇怪的是实际上没有数据，请联系开发者！");
                return;
            }


            base.OnReceive(context);
        }

        protected override void OnStart()
        {
            _discuss ??= ForumFactory.CreateDiscuss("Random Thread Name", "", CharacterEngine.Character_AuthorID);

            if (_discuss.Members is null)
            {
                _discuss.Members = new List<string>();
                SetDirtyState(true);
            }
            
            if (_discuss.Threads is null)
            {
                _discuss.Threads = new List<ForumObject>();
                SetDirtyState(true);
            }
            
            Initialize();
            base.OnStart();
        }


        protected override void OnCommandProc(Verbose verbose)
        {
            if (verbose == Verbose.Save)
            {
                Save();
            }

            base.OnCommandProc(verbose);
        }

        public ICommandEX SaveCommand { get; }
    }
}